/**
 ****************************************************************************************************
 * @file        my_2D.h
 * @author      嵌入式小书虫
 * @version     V1.0
 * @date        2020-04-17
 * @brief       my2d 驱动代码
 ****************************************************************************************************
 *
 * 修改说明
 * V1.0 20200417
 * 第一次发布
 <欢迎关注微信公众号：嵌入式小书虫>
 *
 ****************************************************************************************************
 */

#ifndef _MY_2D_H
#define _MY_2D_H

#include "./BSP/LCD/lcd.h"

#include<string.h>
#include<stdbool.h>

#define LCD_WIDTH   320
#define LCD_HEIGHT  240

#define PFB_WIDTH   10
#define PFB_HEIGHT  10
#define PFB_SIZE PFB_WIDTH * PFB_HEIGHT

#define  DIRTY_REGIONS_ENABLE  1

#   define __MY2D_RGB(__R, __G, __B)    ((((uint16_t)(__R) & 0xFF) >> 3 << 11)   |   \
                                    (((uint16_t)(__G) & 0xFF) >> 2 << 5)    |   \
                                    (((uint16_t)(__B) & 0xFF) >> 3 << 0)    )

/* GLCD RGB color definitions                            */
#define MY2D_GLCD_COLOR_BLACK        __MY2D_RGB(   0,   0,   0  )
#define MY2D_GLCD_COLOR_NAVY         __MY2D_RGB(   0,   0, 128  )
#define MY2D_GLCD_COLOR_DARK_GREEN   __MY2D_RGB(   0, 128,   0  )
#define MY2D_GLCD_COLOR_DARK_CYAN    __MY2D_RGB(   0, 128, 128  )
#define MY2D_GLCD_COLOR_MAROON       __MY2D_RGB( 128,   0,   0  )
#define MY2D_GLCD_COLOR_PURPLE       __MY2D_RGB( 128,   0, 128  )
#define MY2D_GLCD_COLOR_OLIVE        __MY2D_RGB( 128, 128,   0  )
#define MY2D_GLCD_COLOR_LIGHT_GREY   __MY2D_RGB( 192, 192, 192  )
#define MY2D_GLCD_COLOR_DARK_GREY    __MY2D_RGB( 128, 128, 128  )
#define MY2D_GLCD_COLOR_BLUE         __MY2D_RGB(   0,   0, 255  )
#define MY2D_GLCD_COLOR_GREEN        __MY2D_RGB(   0, 255,   0  )
#define MY2D_GLCD_COLOR_CYAN         __MY2D_RGB(   0, 255, 255  )
#define MY2D_GLCD_COLOR_RED          __MY2D_RGB( 255,   0,   0  )
#define MY2D_GLCD_COLOR_MAGENTA      __MY2D_RGB( 255,   0, 255  )
#define MY2D_GLCD_COLOR_YELLOW       __MY2D_RGB( 255, 255, 0    )
#define MY2D_GLCD_COLOR_WHITE        __MY2D_RGB( 255, 255, 255  )


typedef enum {
    my2D_fsm_rt_err          = -1,    //!< fsm error
    my2D_fsm_rt_cpl          = 0,     //!< fsm complete
    my2D_fsm_rt_on_going     = 1,     //!< fsm on-going
    my2D_fsm_rt_wait_for_obj = 2,     //!< fsm wait for IPC object
    my2D_fsm_rt_async        = 3,     //!< fsm work asynchronously, please check it later.
    my2D_fsm_rt_wait_for_res = 4,     //!< wait for resource
} my2d_fsm_rt_t;

// typedef struct my2d_tile{
//    char i;
// }my2d_tile_t;

 
 typedef struct my2d_size_t {
    int16_t iWidth;                     //!< width of an rectangular area
    int16_t iHeight;                    //!< height of an rectangular area
} my2d_size_t;
typedef struct my2d_location_t {
    int16_t iX;                         //!< x in Cartesian coordinate system
    int16_t iY;                         //!< y in Cartesian coordinate system
} my2d_location_t;
 
typedef struct my2d_region_t {
    my2d_location_t tLocation;//implement_ex(arm_2d_location_t, tLocation); //!< the location (top-left corner)
    my2d_size_t   tSize;//implement_ex(arm_2d_size_t, tSize);         //!< the size
} my2d_region_t;
 
typedef struct my2d_op_fill_cl_t{
    char i;
}my2d_op_fill_cl_t;

typedef struct my2d_tile_t my2d_tile_t;
struct my2d_tile_t {
    /*implement_ex(struct {
        uint8_t    bIsRoot              : 1;                                    //!< is this tile a root tile
        uint8_t    bHasEnforcedColour   : 1;                                    //!< does this tile contains enforced colour info
        uint8_t    bDerivedResource     : 1;                                    //!< indicate whether this is a derived resources (when bIsRoot == 0)
        uint8_t    bVirtualResource     : 1;                                    //!< indicate whether the resource should be loaded on-demand
        uint8_t    bVirtualScreen       : 1;                                    //!< DO NOT USE! indicate whether the tile is considered as the virtual screen, it is used in dirty region calculation
        uint8_t    u3ExtensionID        : 3;                                    //!< Tile Extension ID
        arm_2d_color_info_t    tColourInfo;                                     //!< enforced colour

        union {
            uint16_t                    : 16;
            struct {
                uint8_t bIsNewFrame     : 1;
                uint8_t bIsDryRun       : 1;
            }PFB;
        } Extension;
        
    }, tInfo);*/

    //implement_ex(arm_2d_region_t, tRegion);                                     //!< the region of the tile
    my2d_region_t  tRegion;
    union {
        /* when bIsRoot is true, phwBuffer is available,
         * otherwise ptParent is available
         */
        my2d_tile_t       *ptParent;                                          //!< a pointer points to the parent tile
        uint8_t             *pchBuffer;                                         //!< a pointer points to a buffer in a 8bit colour type
        uint16_t            *phwBuffer;                                         //!< a pointer points to a buffer in a 16bit colour type
        uint32_t            *pwBuffer;                                          //!< a pointer points to a buffer in a 32bit colour type

        intptr_t            nAddress;                                           //!< a pointer in integer
    };
};

/******************************************************************************************/
typedef my2d_fsm_rt_t my2d_helper_draw_handler_t( 
                                          //void *pTarget,
                                          //const my2d_tile_t *ptTile,
                                          bool bIsNewFrame);
struct my2D_scene{
    void (*fnOnLoad)(struct my2D_scene *ptScene);
    //void (*fnOnLoad)(arm_2d_scene_t *ptThis);                                   //!< on load event handler
    void (*fnOnBGStart)(struct my2D_scene *ptThis);                                //!< on-start-drawing-background event handler
    void (*fnOnBGComplete)(struct my2D_scene *ptThis);                             //!< on-complete-drawing-background event handler
    void (*fnOnFrameStart)(struct my2D_scene *ptThis);                             //!< on-frame-start event handler
    void (*fnOnFrameCPL)(struct my2D_scene *ptThis);                               //!< on-frame-complete event handler
    my2d_helper_draw_handler_t *fnScene;
};
 
typedef struct my2D_scene my2D_scene_t;

struct my_2D_op_t2{
    int16_t state;
    my2D_scene_t *scene;
    uint16_t pfb_data[PFB_SIZE];
    my2d_region_t pfb_region;
    
    uint8_t background_draw_flag;
#if DIRTY_REGIONS_ENABLE  
    
    my2d_region_t* ptDirtyRegions;
    uint8_t DirtyRegions_num;
    uint8_t DirtyRegions_run_num;
    uint8_t Row_priority_flag ;
    
#endif
    //my2d_size_t pfb_size;
    
    //int16_t ix_num;
    //int16_t iy_num;
    
    //============
    //my2d_tile_t *pTarget;
    //my2d_tile_t *ptTile;
    bool bIsNewFrame;

};
typedef struct{
    uint8_t *pchBuffer;
    uint16_t offset;
    uint16_t char_width;
    uint8_t WidthOffset;
    my2d_size_t   tSize;
}my2d_font_tile_t;

typedef struct my_2D_op_t2 my_2D_op_t;
extern my_2D_op_t my_2D_op;
#define MY_2D_SCENE  my_2D_op.scene

void my2d_init();
void my2d_disp_adapter0_task();
my2d_fsm_rt_t my2d_scene_player_task();
my2d_fsm_rt_t __my2d_disp_adapter0_task(void);
void my2d_Disp0_DrawBitmap (uint32_t x, 
                         uint32_t y, 
                         uint32_t width, 
                         uint32_t height, 
                         const uint8_t *bitmap);
//=======================================================================================


#endif
